﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Globalization;
using System.Xml;

namespace GPCodeConjurer
{
	public class Line : Node
	{
		public Line()
		{
			this.Pt1 = PointF.Empty;
			this.Pt2 = Point.Empty;
			this.GrabHandles.Add("1", new GrabHandle(this, HandleMoveBehavior.All, ContentAlignment.MiddleCenter));
			this.GrabHandles.Add("2", new GrabHandle(this, HandleMoveBehavior.All, ContentAlignment.MiddleCenter));
		}

		public Line(PointF pt1, PointF pt2)
			: this()
		{
			this.Pt1 = pt1;
			this.Pt2 = pt2;
			this.RelocateGrabHandles();
		}


		public PointF Pt1 { get; set; }
		public PointF Pt2 { get; set; }



		internal override void DrawPath(GraphicsPath gp)
		{
			gp.AddLine(this.Pt1, this.Pt2);
		}


		internal override void OnGrabHandleMove(HandleMovedEventArgs e)
		{
			this.Pt1 = this.GrabHandles["1"].Location;
			this.Pt2 = this.GrabHandles["2"].Location;
		}


		internal override void OnMoved(NodeMovedEventArgs e)
		{
			Size diff = e.Difference;
			this.Pt1 = new PointF(this.Pt1.X + diff.Width, this.Pt1.Y + diff.Height);
			this.Pt2 = new PointF(this.Pt2.X + diff.Width, this.Pt2.Y + diff.Height);

			// move the handles also
			foreach (var kvp in this.GrabHandles)
			{
				kvp.Value.Location = new Point(kvp.Value.Location.X + diff.Width, kvp.Value.Location.Y + diff.Height);
			}
		}


		public override string CreateCode()
		{
			string c = string.Empty;
			if (this.StartFigure)
				c += Environment.NewLine + "\tgp.StartFigure();";
			c += string.Format(
				"\r\n\tgp.AddLine(new PointF({0}f, {1}f), new PointF({2}f, {3}f));",
				this.Pt1.X,
				this.Pt1.Y,
				this.Pt2.X,
				this.Pt2.Y);
			if (this.CloseFigure)
				c += Environment.NewLine + "\tgp.CloseFigure();";
			return c;
		}


		internal override bool PointIsOnNode(Point pt)
		{
			using (GraphicsPath gp = new GraphicsPath())
			{
				Pen pen = new Pen(Color.Black, 10f);
				this.DrawPath(gp);
				gp.Widen(pen);
				pen.Dispose();
				return gp.IsVisible(pt);
			}
		}


		internal override Rectangle Rect
		{
			get 
			{
				return Rectangle.FromLTRB(
					Convert.ToInt32(Math.Min(this.Pt1.X, this.Pt2.X)),
					Convert.ToInt32(Math.Min(this.Pt1.Y, this.Pt2.Y)),
					Convert.ToInt32(Math.Max(this.Pt1.X, this.Pt2.X)),
					Convert.ToInt32(Math.Max(this.Pt1.Y, this.Pt2.Y))
					);
			}
		}


		internal override void RelocateGrabHandles()
		{
			this.GrabHandles["1"].Location = this.Pt1.ToPoint();
			this.GrabHandles["2"].Location = this.Pt2.ToPoint();
		}


		public override object Clone()
		{
			Line n = new Line(this.Pt1, this.Pt2);
			return n;
		}


		public override XmlElement Serialize(XmlDocument xmlDoc)
		{
			XmlElement n = xmlDoc.CreateElement("Line");
			this.SeralizeStartCloseFigure(n);
			n.AppendChild(this.Pt1.Serialize(xmlDoc));
			n.AppendChild(this.Pt2.Serialize(xmlDoc));
			return n;
		}


		public override void Deserialize(XmlElement seralizedElement)
		{
			this.DeseralizeStartCloseFigure(seralizedElement);
			this.Pt1 = ExtensionHelpers.DeserializePointF(seralizedElement.ChildNodes[0] as XmlElement);
			this.Pt2 = ExtensionHelpers.DeserializePointF(seralizedElement.ChildNodes[1] as XmlElement);
		}



		public override string ToString()
		{
			return "Line";
		}

	}
}
